"""
让模型干活
1、分析问题，找到工具
2、调用工具
3、将工具的结果返回
4、[optional] 继续调用模型 -- 多层调用
"""
import json
import os
from typing import Dict
from tools.llm_tool import llm_call
from my_langchain.mcp import general_inquiry, menu_inquiry, delivery_check_tool


class SmartRestaurantAssistant:
    """小助手 (AiService.ChatAssistant"""

    def __init__(self):
        self.api_key = os.getenv("ALIBABA_BAILIAN_API_KEY")

        self.tools = {
            "general_inquiry": general_inquiry,  # key: 工具名 value: 实际的工具对象
            "menu_inquiry": menu_inquiry,
            "delivery_check_tool": delivery_check_tool
        }

        # 意图分析系统指令
        self.intent_instruction = """你是一个智能餐厅助手的意图分析器。
        请分析用户问题，选择最合适的工具来处理：

        工具说明：
        1. general_inquiry: 处理餐厅常规咨询（营业时间、地址、电话、优惠活动等）
        2. menu_inquiry: 智能菜品推荐和咨询（推荐菜品、介绍菜品、询问菜品信息等）
        3. delivery_check_tool: 配送范围检查（查询某个地址是否在配送范围内）

        请只返回JSON格式：
        {
            "tool": "工具名称",
            "query": "处理后的用户问题"
        }

        示例：
        用户："你们几点营业？" -> {"tool": "general_inquiry", "query": "营业时间"}
        用户："推荐个川菜" -> {"tool": "menu_inquiry", "query": "推荐个川菜"}
        用户："推荐一些菜系" -> {"tool": "menu_inquiry", "query": "推荐菜系"}
        用户："我想吃辣一点的菜" -> {"tool": "menu_inquiry", "query": "推荐风味辣的菜"}
        用户："能送到江西财经大学吗？" -> {"tool": "delivery_check_tool", "query": "江西财经大学"}
        
        要求:
        严格按照返回格式标准，返回格式准确、正确的Json字符串
        """

    # 意图分析函数
    def analyze_intent(self, user_query: str) -> Dict[str, str]:
        """
        :param user_query: 输入的原始问题
        :return:
        dict {
            "tool": "工具名称",
            "query": "处理后的用户问题"
        }
        """
        try:
            # 调用模型进行意图分析
            response = llm_call(user_query, self.intent_instruction)

            # 解析JSON响应
            try:
                result = json.loads(response)
                # 验证工具名称是否有效
                if result.get("tool") in self.tools:
                    return result
                else:
                    # 如果工具名称无效，默认使用常规咨询
                    return {"tool": "general_inquiry", "query": user_query}
            except json.JSONDecodeError:
                # JSON解析失败，尝试从响应中提取工具信息
                if "menu" in response.lower() or "菜品" in response or "推荐" in response:
                    return {"tool": "menu_inquiry", "query": user_query}
                elif "配送" in response or "delivery" in response.lower() or "送到" in response:
                    return {"tool": "delivery_check_tool", "query": user_query}
                else:
                    return {"tool": "general_inquiry", "query": user_query}

        except Exception as e:
            print(f"意图分析出错: {e}")
            # 默认使用常规咨询
            return {"tool": "general_inquiry", "query": user_query}

    # 执行指定的工具
    def execute_tool(self, tool_name: str, query: str) -> str:
        """
        :param tool_name: 工具名称
        :param query: 查询内容
        :return: 工具执行结果
        """
        try:
            tool_func = self.tools.get(tool_name)
            if not tool_func:
                return f"未找到工具: {tool_name}"

            # 根据工具类型传递不同的参数
            if tool_name == "general_inquiry":
                # general_inquiry需要query和context两个参数
                result = tool_func.invoke({"query": query})
            elif tool_name == "menu_inquiry":
                # menu_inquiry只需要query参数
                result = tool_func.invoke({"query": query})
            elif tool_name == "delivery_check_tool":
                # delivery_check_tool需要address和travel_mode参数
                result = tool_func.invoke({"address": query})
            else:
                # 默认只传query参数
                general_tool_func = self.tools["general_inquiry"]
                result = general_tool_func.invoke({"query": query})

            print(f"{tool_name}工具调用成功")
            return result

        except Exception as e:
            print("工具执行期间出错")
            return f"工具调用失败: {str(e)}"

    # 对话聊天的入口
    def chat(self, query: str) -> str:
        try:
            # 1、根据输入的问题，进行语义分析
            selected_tool_map = self.analyze_intent(query)
            selected_tool_name = selected_tool_map["tool"]
            processed_query = selected_tool_map["query"]
            # 2、调用对应的工具执行
            tool_result = self.execute_tool(selected_tool_name, processed_query)
            # [继续调用其他模型]
            return tool_result
        except Exception as e:
            print(f"聊天助手对话失败，{str(e)}")
            return f"聊天助手对话失败"


def LangchainMain(input_query: str = None):
    if not input_query:
        input_query = "请给我推荐辣的菜系，还有你们总共多少道菜？"
    smart_assistant = SmartRestaurantAssistant()
    response = smart_assistant.chat(input_query)
    return response


if __name__ == "__main__":
    print(LangchainMain())
